local frame
local OptionHouse
local TOTAL_ROWS = 14
local CREATED_ROWS = 0

OHManage = {}

--[[
LOAD MANAGERS

AddonLoader (Ace2 loader)
Format: X-LoadOn-*
Saved Var: AddonLoader.db.profile.overrides[addon name] = "X-LoadOn-<mode>"
Check-for-used: None, scan all of valid
Valid: Always, AuctionHouse, Arena, Bank, Battleground, Combat, Crafting,
Group, Guild, Instance, Mailbox, Merchant, NotResting, PvPFlagged,
Raid, Resting

SupplyAndDemand
Format: X-S&D-*
Check-for-used: X-S&D-Placeholder
Valid: Always, InParty, InRaid, Resting, NotResting, AtMail, AtMerchant,
Crafting, PvPFlagged, Class

Class can be seperated by anything, but it must be in upper case eg "ROGUE, WARRIOR"
]]


local STATUS_COLORS = {
	["DISABLED"] = "|cff9d9d9d",
	["NOT_DEMAND_LOADED"] = "|cffff8000",
	["DEP_NOT_DEMAND_LOADED"] = "|cffff8000",
	["LOAD_ON_DEMAND"] = "|cff1eff00",
	["DISABLED_AT_RELOAD"] = "|cffa335ee"
}

local L = {
	["LOAD"] = "Load",
	["RELOAD_UI"] = "Reload UI",
	["ENABLE_ALL"] = "Enable All",
	["DISABLE_ALL"] = "Disable All",
	["AUTHOR"] = "Author: %s",
	["VERSION"] = "Version: %s",
	["DEPENDENCIES"] = "Dependencies: %s",
	["DISABLED_AT_RELOAD"] = "Disabled on UI Reload",
	["LOAD_ON_DEMAND"] = "Loadable on Demand",
	["NOT_DEMAND_LOADED"] = "Not loadable on demand",
	["ADDON_MANAGEMENT"] = "Management",
	["NAME"] = "Name",
	["STATUS"] = "Status",
	["NOTES"] = "Notes: %s",
	["ENABLE_DEPS"] = "Would you like to enable the %d dependencies for %s?",
	["ENABLE_DEP"] = "Would you like to enable the %d dependency for %s?",
	["ENABLE_CHILDREN"] = "Would you like to enable the %s children addon for %s?",
	["ENABLE_CHILD"] = "Would you like to enable the %s child addon for %s?",
}

local function sortManagementAddons(a, b)
	if( not b ) then
		return false
	end

	if( frame.sortOrder ) then
		if( frame.sortType == "name" ) then
			return ( string.lower(a.title) < string.lower(b.title) )
		elseif( frame.sortType == "status" ) then
			return ( a.reason < b.reason )
		end

		return ( string.lower(a.title) < string.lower(b.title) )

	else
		if( frame.sortType == "name" ) then
			return ( string.lower(a.title) > string.lower(b.title) )
		elseif( frame.sortType == "status" ) then
			return ( a.reason > b.reason )
		end

		return ( string.lower(a.title) > string.lower(b.title) )
	end
end

local function createDependencies(...)
	if( select("#", ...) == 0 ) then
		return nil
	end

	local deps = ""
	for i=1, select("#", ...) do
		if( i > 1 ) then
			deps = deps .. ", " .. select(i, ...)
		else
			deps = select(i, ...)
		end
	end

	return deps
end

local function updateManageList()
	if( not frame:IsShown() or not frame.scroll ) then
		return
	end

	OptionHouse:UpdateScroll(frame.scroll, #(frame.addons))
	
	for i=1, CREATED_ROWS do
		frame.rows[i].name:Hide()
		frame.rows[i].enabled:Hide()
		frame.rows[i].button:Hide()
		frame.rows[i].reason:Hide()
	end

	for i=1, TOTAL_ROWS do
		local row = frame.rows[i]
		local addon = frame.addons[frame.scroll.offset + i]

		if( addon ) then
			if( addon.color ) then
				addon.reason = addon.color .. addon.reason .. "|r"
				addon.name = addon.color .. addon.name .. "|r"
			end

			row.name:SetText(addon.name)
			row.name:Show()

			row.enabled.text = addon.tooltip
			row.enabled.addon = addon.id
			row.enabled:SetChecked(addon.isEnabled)
			row.enabled:Show()

			row.reason:SetText(addon.reason)
			row.reason:Show()

			-- Shift the reason to the right if no button so we don't have ugly blank space
			if( not addon.isLoD ) then
				row.reason:SetPoint("RIGHT", row.button, "RIGHT", -5, 0)
				row.button:Hide()
			else
				row.reason:SetPoint("RIGHT", row.button, "LEFT", -5, 0)
				row.button.addon = addon.id
				row.button:Show()
			end
		end
	end
end

local function createManageList()
	local searchBy = string.trim(string.lower(frame.search:GetText()))
	if( searchBy == "" or frame.search.searchText ) then
		searchBy = nil
	end

	frame.addons = {}
	for i=1, GetNumAddOns() do
		if( not searchBy or ( searchBy and string.find(string.lower((GetAddOnInfo(i))), searchBy) ) ) then
			local name, title, notes, enabled, loadable, reason, security = GetAddOnInfo(i)
			local isLoaded = IsAddOnLoaded(i)
			local isLoD = IsAddOnLoadOnDemand(i)
			local author = GetAddOnMetadata(i, "Author")
			local version = GetAddOnMetadata(i, "Version")
			local dependencies = createDependencies(GetAddOnDependencies(i))
			local dataTitle, dataAuthor, dataVersion = OptionHouse:GetAddOnData(name)
			local color
			
			title = dataTitle or title
			
			if( dataVersion ) then
				version = dataVersion
			elseif( type(version) == "string" ) then
				-- Strip out some of the common strings from version meta data
				version = string.gsub(version, "%$Revision: (%d+) %$", "%1")
				version = string.gsub(version, "%$Rev: (%d+) %$", "%1")
				version = string.gsub(version, "%$LastChangedRevision: (%d+) %$", "%1")
				version = string.trim(version)
			else
				version = nil
			end

			if( dataAuthor ) then
				author = dataAuthor
			elseif( type(author) ~= "string" ) then
				author = nil
			end

			if( reason == "DISABLED" ) then
				color = STATUS_COLORS[reason]
				reason = TEXT(ADDON_DISABLED)
				isLoD = nil

			-- Addons not LoD and was disabled
			elseif( reason == "NOT_DEMAND_LOADED" ) then
				color = STATUS_COLORS[reason]
				reason = L["NOT_DEMAND_LOADED"]
				
			-- One of the dependencies isn't LoD
			elseif( reason == "DEP_NOT_DEMAND_LOADED" ) then
				color = STATUS_COLORS[reason]
				reason = TEXT(ADDON_DEP_NOT_DEMAND_LOADED)
				isLoD = nil
				
			elseif( loadable and isLoD and not isLoaded and enabled ) then
				reason = L["LOAD_ON_DEMAND"]
				color = STATUS_COLORS["LOAD_ON_DEMAND"]
				
			-- Covers any other reason
			elseif( reason ) then
				reason = TEXT(getglobal("ADDON_" .. reason))
				color = STATUS_COLORS["ADDON_" .. reason]
			
			-- Currently loaded, but will be disabled at reload
			elseif( isLoaded and not enabled ) then
				reason = L["DISABLED_AT_RELOAD"]
				color = STATUS_COLORS["DISABLED_AT_RELOAD"]
				isLoD = nil

			-- Addon is LoD, but it was already loaded/enabled so dont show the button
			elseif( isLoD and isLoaded and enabled ) then
				reason = nil
				isLoD = nil
			end

			local tooltip = "|cffffffff" .. title .. "|r"

			if( author ) then
				tooltip = tooltip .. "\n" .. string.format(L["AUTHOR"], author)
			end

			if( version ) then
				tooltip = tooltip .. "\n" .. string.format(L["VERSION"], version)
			end

			if( dependencies ) then
				tooltip = tooltip .. "\n" .. string.format(L["DEPENDENCIES"], dependencies)
			end
		
			if( notes ) then
				tooltip = tooltip .. "\n" .. string.format(L["NOTES"], notes)
			end

			table.insert(frame.addons, {name = title, id = i, color = color, title = title, author = author, version = version, tooltip = tooltip, dependencies = dependencies, reason = reason or "", isEnabled = enabled, isLoD = isLoD})
		end
	end

	table.sort(frame.addons, sortManagementAddons)
	updateManageList()
end

local function loadAddon(self)
	-- Load all of the LoD dependencies
	for _, dep in pairs({GetAddOnDependencies(self.addon)}) do
		if( not IsAddOnLoaded(dep) and IsAddOnLoadOnDemand(dep) ) then
			LoadAddOn(dep)
		end
	end
	
	LoadAddOn(self.addon)
	createManageList()
end

local function enableChildren(self, children)
	for _, child in pairs(children) do
		EnableAddOn(child)
	end
	
	createManageList()
end

local function enableAddon(self, addon, useDeps)
	EnableAddOn(addon)
	
	if( useDeps ) then
		for _, dep in pairs({GetAddOnDependencies(addon)}) do
			if( not select(4, GetAddOnInfo(dep)) ) then
				EnableAddOn(dep)
			end
		end
	end

	createManageList()
end

local function isAddonChildOf(parent, ...)
	if( select("#", ...) == 0 ) then
		return nil
	end
	
	if( type(parent) == "number" ) then
		parent = (GetAddOnInfo(parent))
	end
	
	for i=1, select("#", ...) do
		if( select(i, ...) == parent ) then
			return true
		end
	end
	
	return nil
end

local function toggleAddOnStatus(self)
	if( select(4, GetAddOnInfo(self.addon)) ) then
		PlaySound("igMainMenuOptionCheckBoxOff")
		DisableAddOn(self.addon)

		createManageList()
	else
		PlaySound("igMainMenuOptionCheckBoxOn")
		
		local addonEnabled
		
		-- ENABLING THE DEPENDENCIES OF AN ADDON
		if( OptionHouseDB.dependMode ~= "no" ) then
			if( GetAddOnDependencies(self.addon) ) then
				-- Ask before enabling children
				if( OptionHouseDB.dependMode == "ask" ) then
					if( not StaticPopupDialogs["ENABLE_ADDON_DEPS"] ) then
						OHManage.EnableAddon = enableAddon

						StaticPopupDialogs["ENABLE_ADDON_DEPS"] = {
							button1 = YES,
							button2 = NO,
							OnAccept = function(id)
								OHManage:EnableAddon(id, true)
							end,
							OnCancel = function(id)
								OHManage:EnableAddon(id)
							end,
							timeout = 0,
							whileDead = 1,
							hideOnEscape = 1,
							multiple = 1,
						}
					end
					
					local totalDeps = 0
					for _, dep in pairs({GetAddOnDependencies(self.addon)}) do
						if( not select(4, GetAddOnInfo(dep)) ) then
							totalDeps = totalDeps + 1
						end
					end					

					if( totalDeps > 0 ) then
						if( totalDeps > 1 ) then
							StaticPopupDialogs["ENABLE_ADDON_DEPS"].text = L["ENABLE_DEPS"]
						else
							StaticPopupDialogs["ENABLE_ADDON_DEPS"].text = L["ENABLE_DEP"]
						end
						
					
						-- DAMN YOU SLOUKEN >=(
						local dialog = StaticPopup_Show("ENABLE_ADDON_DEPS", totalDeps, (GetAddOnInfo(self.addon)))
						if( dialog ) then
							dialog.data = self.addon
						end
						addonEnabled = true
					end
				else
					enableAddon(self, self.addon, true)
					addonEnabled = true
				end
			end
		end
		
		-- Didn't enable it already through the dep mode
		if( not addonEnabled ) then
			enableAddon(self, self.addon)
		end
		
		-- ENABLING THE CHILDREN OF AN ADDON
		-- BigWigs, LightHeaded (damn clad), ect
		if( OptionHouseDB.childMode ~= "no" ) then
			-- Find all of the addons with us as a dependency
			local children = {}
			for i=1, GetNumAddOns() do
				if( not select(4, GetAddOnInfo(i) ) and isAddonChildOf(self.addon, GetAddOnDependencies(i)) ) then
					table.insert(children, i)
				end
			end
						
			if( #(children) > 0 ) then
				-- Ask for enabling
				if( OptionHouseDB.childMode == "ask" ) then
					if( not StaticPopupDialogs["ENABLE_ADDON_CHILDREN"] ) then
						OHManage.EnableChildren = enableChildren

						StaticPopupDialogs["ENABLE_ADDON_CHILDREN"] = {
							button1 = YES,
							button2 = NO,
							OnAccept = function(children)
								OHManage:EnableChildren(children)
							end,
							timeout = 0,
							whileDead = 1,
							hideOnEscape = 1,
							multiple = 1,
						}
					end
					
					if( #(children) > 0 ) then
						if( #(children) > 1 ) then
							StaticPopupDialogs["ENABLE_ADDON_CHILDREN"].text = L["ENABLE_CHILDREN"]
						else
							StaticPopupDialogs["ENABLE_ADDON_CHILDREN"].text = L["ENABLE_CHILD"]
						end
						
					
						-- DAMN YOU SLOUKEN >=(
						local dialog = StaticPopup_Show("ENABLE_ADDON_CHILDREN", #(children), (GetAddOnInfo(self.addon)))
						if( dialog ) then
							dialog.data = children
						end
					end
					
				-- Always enable children
				elseif( OptionHouseDB.childMode == "yes" ) then
					enableChildren(self, children)
				end
				
				return
			end
		end
	end
end

local function showTooltip(self)
	if( self.text ) then
		GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
		GameTooltip:SetText(self.text, nil, nil, nil, nil, 1)
	end
end

local function hideTooltip()
	GameTooltip:Hide()
end

local function sortManageClick(self)
	if( self.sortType ) then
		if( self.sortType ~= frame.sortType ) then
			frame.sortOrder = false
			frame.sortType = self.sortType
		else
			frame.sortOrder = not frame.sortOrder
		end

		table.sort(frame.addons, sortManagementAddons)
		updateManageList()
	end
end

local function createRows()
	local path, size, border = GameFontHighlightSmall:GetFont()
	size = OptionHouseDB.manageFontSize

	if( not frame.testFS ) then
		frame.testFS = frame:CreateFontString()
	end
		
	frame.testFS:SetFont(path, size, border)
	frame.testFS:SetText("*")

	local spacing = -12 - frame.testFS:GetHeight()		
	
	TOTAL_ROWS = ceil(305 / abs(spacing))
	
	if( not frame.rows ) then
		frame.rows = {}
	end
		
	for i=1, TOTAL_ROWS do
		local row
		if( not frame.rows[i] ) then
			CREATED_ROWS = CREATED_ROWS + 1
			
			row = {}
			frame.rows[i] = row
			
			row.enabled = CreateFrame("CheckButton", nil, frame, "OptionsCheckButtonTemplate")
			row.button = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
			row.reason = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
			row.name = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
		else
			row = frame.rows[i]
		end

		-- Enable checkbox
		row.enabled:SetWidth(22)
		row.enabled:SetHeight(22)
		row.enabled:SetScript("OnClick", toggleAddOnStatus)
		row.enabled:SetScript("OnEnter", showTooltip)
		row.enabled:SetScript("OnLeave", hideTooltip)

		-- Load a LoD addon
		row.button:SetWidth(50)
		row.button:SetHeight(18)
		row.button:SetText(L["LOAD"])
		row.button:SetScript("OnClick", loadAddon)

		-- Reason (Disabled/Not LoD/LoD/Dependency Missing/ect)
		row.reason:SetFont(path, size, border)

		-- Addon name
		row.name:SetFont(path, size, border)
		row.name:SetHeight(22)
		row.name:SetJustifyH("LEFT")
		row.name:SetNonSpaceWrap(false)

		if( i > 1 ) then
			row.enabled:SetPoint("TOPLEFT", frame.rows[i-1].enabled, "TOPLEFT", 0, spacing)
			row.button:SetPoint("TOPRIGHT", frame.rows[i-1].button, "TOPRIGHT", 0, spacing)
			row.name:SetPoint("TOPLEFT", frame.rows[i-1].name, "TOPLEFT", 0, spacing)
			row.reason:SetPoint("RIGHT", frame.rows[i-1].button, "LEFT", -5, 0)
		else
			row.enabled:SetPoint("TOPLEFT", frame.sortButtons[1], "TOPLEFT", 0, -22)
			row.button:SetPoint("TOPRIGHT", frame.sortButtons[2], "TOPRIGHT", 4, -22)
			row.name:SetPoint("LEFT", row.enabled, "RIGHT", 5, 0)
			row.reason:SetPoint("RIGHT", row.button, "LEFT", -5, 0)
		end
	end
end

local function addonManageTab(hide)
	local name = "OptionHouseManageFrame"
	frame = OptionHouse:GetFrame("manage")
	
	if( frame and hide ) then
		frame:Hide()
		return
	elseif( hide ) then
		return
	elseif( not frame ) then
		frame = CreateFrame("Frame", nil, OptionHouse:GetFrame("main"))
		frame.sortOrder = true
		frame.sortType = "name"
		frame:SetFrameStrata("MEDIUM")
		frame:SetAllPoints(OptionHouse:GetFrame("main"))
		frame:RegisterEvent("ADDON_LOADED")
		frame:SetScript("OnEvent", createManageList)
		frame.sortButtons = {}
	
		OptionHouse:CreateSearchInput(frame, createManageList)

		local disableAll = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
		disableAll:SetWidth(80)
		disableAll:SetHeight(22)
		disableAll:SetPoint("BOTTOMRIGHT", OptionHouse:GetFrame("main"), "BOTTOMRIGHT", -8, 14)
		disableAll:SetText(L["DISABLE_ALL"])
		disableAll:SetScript("OnClick", function()
			DisableAllAddOns()
			EnableAddOn("OptionHouse")
			createManageList()
		end)

		local enableAll = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
		enableAll:SetWidth(80)
		enableAll:SetHeight(22)
		enableAll:SetPoint("RIGHT", disableAll, "LEFT")
		enableAll:SetText(L["ENABLE_ALL"])
		enableAll:SetScript("OnClick", function()
			EnableAllAddOns()
			createManageList()
		end)

		local reloadUI = CreateFrame("Button", nil, frame, "UIPanelButtonGrayTemplate")
		reloadUI:SetWidth(80)
		reloadUI:SetHeight(22)
		reloadUI:SetPoint("RIGHT", enableAll, "LEFT")
		reloadUI:SetText(L["RELOAD_UI"])
		reloadUI:SetScript("OnClick", ReloadUI)

		local button = CreateFrame("Button", nil, frame)
		button:SetScript("OnClick", sortManageClick)
		button:SetHeight(20)
		button:SetWidth(75)
		button:SetTextFontObject(GameFontNormal)
		button.sortType = "name"
		button:SetText(L["NAME"])
		button:SetWidth(button:GetFontString():GetStringWidth() + 3)
		button:SetPoint("TOPLEFT", frame, "TOPLEFT", 25, -73)
		button:Show()
		
		frame.sortButtons[1] = button

		button = CreateFrame("Button", nil, frame)
		button:SetScript("OnClick", sortManageClick)
		button:SetHeight(20)
		button:SetWidth(75)
		button:SetTextFontObject(GameFontNormal)
		button.sortType = "status"
		button:SetText(L["STATUS"])
		button:SetWidth(button:GetFontString():GetStringWidth() + 3)
		button:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -50, -73)
		button:Show()
		
		frame.sortButtons[2] = button

		-- Create all of the rows for display
		createRows()

		OptionHouse:CreateScrollFrame(frame, TOTAL_ROWS, updateManageList)
		OptionHouse:RegisterFrame("manage", frame)
		
		frame.scroll:SetPoint("TOPLEFT", frame, "TOPLEFT", 25, -76)
		frame.scroll:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -35, 72)
	end

	frame:Show()

	createManageList()
end

function OHManage:Register()
	if( not OptionHouse ) then
		OptionHouse = DongleStub("OptionHouse-1.0")
	end
	
	OptionHouse:RegisterTab(L["ADDON_MANAGEMENT"], addonManageTab, "bid")
end

function OHManage:Reload()
	if( frame ) then
		createRows()

		frame.scroll.displayNum = TOTAL_ROWS
		frame.scroll.bar:SetValueStep(TOTAL_ROWS)

		updateManageList()
	end
end

function OHManage:Unregister()
	if( OptionHouse ) then
		OptionHouse:UnregisterTab(L["ADDON_MANAGEMENT"])
	end
end
